<template>
  <view class="announcement-container">
    <!-- 头部区域 -->
    <view class="header">
      <text class="title">管理员公告</text>
    </view>

    <!-- 添加新闻表单区域 -->
    <view class="form-section">
      <view class="section-title">
        <text>{{ isEditing ? '编辑新闻' : '添加新闻' }}</text>
      </view>
      <view class="form-item">
        <text class="form-label">标题</text>
        <input
          class="form-input"
          v-model="newsForm.title"
          placeholder="请输入新闻标题"
          maxlength="100"
        />
      </view>

      <view class="form-item">
        <text class="form-label">来源</text>
        <input
          class="form-input"
          v-model="newsForm.source"
          placeholder="请输入新闻来源"
          maxlength="50"
        />
      </view>

      <view class="form-item">
        <text class="form-label">链接</text>
        <input
          class="form-input"
          v-model="newsForm.link"
          placeholder="请输入新闻链接"
          maxlength="255"
        />
      </view>

      <view class="form-item">
        <text class="form-label">图片链接</text>
        <input
          class="form-input"
          v-model="newsForm.imageUrl"
          placeholder="请输入图片链接"
          maxlength="255"
        />
      </view>

      <view class="form-item preview-section" v-if="newsForm.imageUrl">
        <text class="form-label">图片预览</text>
        <image
          class="preview-image"
          :src="newsForm.imageUrl"
          mode="aspectFit"
          @error="handleImageError"
        />
      </view>

      <view class="button-group">
        <button class="submit-button" @tap="submitNews">
          {{ isEditing ? '更新新闻' : '发布新闻' }}
        </button>
        <button class="cancel-button" v-if="isEditing" @tap="cancelEditing">取消编辑</button>
      </view>
    </view>

    <!-- 新闻列表 -->
    <view class="news-list">
      <view class="section-title">
        <text>新闻列表</text>
        <text class="refresh-text" @tap="fetchNewsList">刷新</text>
      </view>

      <view class="news-card" v-for="(item, index) in newsList" :key="index">
        <view class="news-header">
          <text class="news-title">{{ item.title }}</text>
          <text class="news-time">{{ formatDateTime(item.createdTime) }}</text>
        </view>

        <view class="news-content">
          <image v-if="item.imageUrl" class="news-image" :src="item.imageUrl" mode="aspectFill" />
          <view class="news-info">
            <text class="news-source">来源: {{ item.source }}</text>
            <text class="news-link" @tap="copyLink(item.link)">链接: {{ item.link }}</text>
          </view>
        </view>

        <view class="news-actions">
          <view class="action-button edit" @tap="editNews(item)">
            <text class="action-text">编辑</text>
          </view>
          <view class="action-button delete" @tap="deleteNews(item.id)">
            <text class="action-text">删除</text>
          </view>
        </view>
      </view>

      <view class="empty-list" v-if="newsList.length === 0">
        <image class="empty-icon" src="/static/images/empty.png" mode="aspectFit" />
        <text class="empty-text">暂无新闻</text>
      </view>

      <!-- 分页信息 -->
      <view class="pagination-info" v-if="newsList.length > 0">
        <text class="page-text">第 {{ pageNum }} 页 / 共 {{ pages }} 页</text>
        <text class="total-text">共 {{ total || newsList.length }} 条</text>
      </view>

      <!-- 加载更多按钮 -->
      <view class="load-more" v-if="newsList.length > 0">
        <button class="load-more-btn" @tap="loadMore" :loading="loading" :disabled="isLastPage">
          {{ loading ? '加载中...' : isLastPage ? '已加载全部' : '加载更多' }}
        </button>
      </view>
    </view>
  </view>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { insertNews, getNewsList, updateNews, deleteNews } from '@/api/news'

interface NewsForm {
  id?: number
  title: string
  source: string
  imageUrl: string
  link: string
}

interface PageInfo<T> {
  total: number
  list: T[]
  pageNum: number
  pageSize: number
  size: number
  startRow: number
  endRow: number
  pages: number
  prePage: number
  nextPage: number
  isFirstPage: boolean
  isLastPage: boolean
  hasPreviousPage: boolean
  hasNextPage: boolean
  navigatePages: number
  navigatePageNums: number[]
  navigateFirstPage: number
  navigateLastPage: number
}

interface ApiResponse<T> {
  code: number
  info: string
  data: T
}

export default defineComponent({
  data() {
    return {
      isEditing: false,
      newsForm: {
        title: '',
        source: '',
        imageUrl: '',
        link: '',
      } as NewsForm,
      newsList: [] as any[],
      // 分页相关
      pageNum: 1,
      pageSize: 5,
      total: 0,
      pages: 0,
      loading: false,
      isLastPage: false,
    }
  },

  methods: {
    // 提交新闻（新增或更新）
    async submitNews() {
      // 表单验证
      if (!this.newsForm.title.trim()) {
        uni.showToast({
          title: '请输入新闻标题',
          icon: 'none',
        })
        return
      }

      if (!this.newsForm.source.trim()) {
        uni.showToast({
          title: '请输入新闻来源',
          icon: 'none',
        })
        return
      }

      if (!this.newsForm.link.trim()) {
        uni.showToast({
          title: '请输入新闻链接',
          icon: 'none',
        })
        return
      }

      uni.showLoading({
        title: this.isEditing ? '更新中...' : '发布中...',
      })

      try {
        if (this.isEditing && this.newsForm.id) {
          // 更新新闻
          const res = await updateNews(this.newsForm)
          if (res.statusCode === 200 && res.data) {
            const responseData = res.data as ApiResponse<any>
            if (responseData.code === 200) {
              uni.showToast({
                title: '更新成功',
                icon: 'success',
              })
              this.resetPagination() // 重置分页
              this.fetchNewsList() // 刷新列表
              this.resetForm()
            } else {
              uni.showToast({
                title: responseData.info || '更新失败',
                icon: 'none',
              })
            }
          }
        } else {
          // 新增新闻
          const res = await insertNews(this.newsForm)
          if (res.statusCode === 200 && res.data) {
            const responseData = res.data as ApiResponse<any>
            if (responseData.code === 200) {
              uni.showToast({
                title: '发布成功',
                icon: 'success',
              })
              this.resetPagination() // 重置分页
              this.fetchNewsList() // 刷新列表
              this.resetForm()
            } else {
              uni.showToast({
                title: responseData.info || '发布失败',
                icon: 'none',
              })
            }
          }
        }
      } catch (error) {
        uni.showToast({
          title: '操作失败，请重试',
          icon: 'none',
        })
        console.error('提交新闻失败:', error)
      } finally {
        uni.hideLoading()
      }
    },

    // 重置分页数据
    resetPagination() {
      this.pageNum = 1
      this.newsList = []
    },

    // 获取新闻列表
    async fetchNewsList() {
      if (this.loading) return

      this.loading = true
      uni.showLoading({
        title: '加载中...',
      })

      try {
        const res = await getNewsList(this.pageNum, this.pageSize)
        if (res.statusCode === 200 && res.data) {
          const responseData = res.data as ApiResponse<PageInfo<any>>
          if (responseData.code === 200 && responseData.data) {
            const pageInfo = responseData.data

            // 如果是第一页，替换列表；否则追加到列表
            if (this.pageNum === 1) {
              this.newsList = pageInfo.list || []
            } else {
              this.newsList = [...this.newsList, ...(pageInfo.list || [])]
            }

            // 更新分页信息
            this.total = pageInfo.total
            this.pages = pageInfo.pages
            this.isLastPage = pageInfo.isLastPage
            this.pageSize = pageInfo.pageSize
          } else {
            uni.showToast({
              title: responseData.info || '获取新闻列表失败',
              icon: 'none',
            })
          }
        }
      } catch (error) {
        uni.showToast({
          title: '获取新闻列表失败',
          icon: 'none',
        })
        console.error('获取新闻列表失败:', error)
      } finally {
        uni.hideLoading()
        this.loading = false
      }
    },

    // 编辑新闻
    editNews(item: any) {
      this.newsForm = {
        id: item.id,
        title: item.title,
        source: item.source,
        imageUrl: item.imageUrl || '',
        link: item.link || '',
      }
      this.isEditing = true

      // 滚动到表单区域
      uni.pageScrollTo({
        scrollTop: 0,
        duration: 300,
      })
    },

    // 删除新闻
    async deleteNews(id: number) {
      uni.showModal({
        title: '确认删除',
        content: '确定要删除这条新闻吗？',
        success: async (res) => {
          if (res.confirm) {
            uni.showLoading({
              title: '删除中...',
            })

            try {
              const res = await deleteNews(id)
              if (res.statusCode === 200 && res.data) {
                const responseData = res.data as ApiResponse<any>
                if (responseData.code === 200) {
                  uni.showToast({
                    title: '删除成功',
                    icon: 'success',
                  })
                  // 从列表中移除
                  this.newsList = this.newsList.filter((item) => item.id !== id)
                } else {
                  uni.showToast({
                    title: responseData.info || '删除失败',
                    icon: 'none',
                  })
                }
              }
            } catch (error) {
              uni.showToast({
                title: '删除失败，请重试',
                icon: 'none',
              })
              console.error('删除新闻失败:', error)
            } finally {
              uni.hideLoading()
            }
          }
        },
      })
    },

    // 取消编辑
    cancelEditing() {
      this.resetForm()
    },

    // 重置表单
    resetForm() {
      this.newsForm = {
        title: '',
        source: '',
        imageUrl: '',
        link: '',
      }
      this.isEditing = false
    },

    // 格式化日期时间
    formatDateTime(dateTimeStr: string | null): string {
      if (!dateTimeStr) return '-'

      try {
        const date = new Date(dateTimeStr)
        const year = date.getFullYear()
        const month = String(date.getMonth() + 1).padStart(2, '0')
        const day = String(date.getDate()).padStart(2, '0')
        const hours = String(date.getHours()).padStart(2, '0')
        const minutes = String(date.getMinutes()).padStart(2, '0')

        return `${year}-${month}-${day} ${hours}:${minutes}`
      } catch (error) {
        return dateTimeStr
      }
    },

    // 复制链接
    copyLink(link: string) {
      uni.setClipboardData({
        data: link,
        success: () => {
          uni.showToast({
            title: '链接已复制',
            icon: 'success',
          })
        },
      })
    },

    // 处理图片加载错误
    handleImageError() {
      uni.showToast({
        title: '图片加载失败',
        icon: 'none',
      })
    },

    // 加载更多数据
    loadMore() {
      if (this.loading) return
      if (this.isLastPage) return

      this.pageNum += 1
      this.fetchNewsList()
    },
  },

  onLoad() {
    this.fetchNewsList()
  },

  onShow() {
    // 每次显示页面时刷新列表
    this.resetPagination()
    this.fetchNewsList()
  },

  // 下拉到底部时加载更多
  onReachBottom() {
    this.loadMore()
  },
})
</script>

<style lang="scss">
// 薰衣草紫主题色
$theme-color: #9370db;
$light-theme-color: #e6e6fa;
$text-color: #333333;
$border-color: #eeeeee;
$danger-color: #ff6b6b;

.announcement-container {
  min-height: 100vh;
  background-color: #f8f8f8;
  padding-bottom: 40rpx;

  .header {
    background: linear-gradient(180deg, $theme-color 0%, $light-theme-color 100%);
    padding: 40rpx 30rpx;

    .title {
      font-size: 36rpx;
      font-weight: bold;
      color: #ffffff;
    }
  }

  .section-title {
    font-size: 32rpx;
    font-weight: bold;
    color: $text-color;
    margin-bottom: 30rpx;
    display: flex;
    justify-content: space-between;
    align-items: center;

    .refresh-text {
      font-size: 26rpx;
      color: $theme-color;
      font-weight: normal;
    }
  }

  .form-section {
    background-color: #ffffff;
    margin: 20rpx;
    border-radius: 12rpx;
    padding: 30rpx;
    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);

    .form-item {
      margin-bottom: 30rpx;

      &:last-child {
        margin-bottom: 0;
      }
    }

    .form-label {
      display: block;
      font-size: 28rpx;
      color: $text-color;
      margin-bottom: 12rpx;
      font-weight: 500;
    }

    .form-input {
      width: 100%;
      height: 80rpx;
      border: 2rpx solid $border-color;
      border-radius: 8rpx;
      padding: 0 20rpx;
      font-size: 28rpx;
      box-sizing: border-box;
    }

    .preview-section {
      .preview-image {
        width: 100%;
        height: 300rpx;
        border-radius: 8rpx;
        background-color: #f7f7f7;
      }
    }

    .button-group {
      display: flex;
      flex-direction: column;
      margin-top: 40rpx;

      .submit-button {
        width: 100%;
        height: 88rpx;
        background: linear-gradient(to right, $theme-color, #8067dc);
        color: #ffffff;
        font-size: 32rpx;
        font-weight: 500;
        border-radius: 44rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        margin-bottom: 20rpx;

        &:active {
          opacity: 0.9;
        }

        &::after {
          border: none;
        }
      }

      .cancel-button {
        width: 100%;
        height: 88rpx;
        background-color: #f7f7f7;
        color: #666666;
        font-size: 32rpx;
        border-radius: 44rpx;
        display: flex;
        align-items: center;
        justify-content: center;

        &:active {
          opacity: 0.9;
        }

        &::after {
          border: none;
        }
      }
    }
  }

  .news-list {
    background-color: #ffffff;
    margin: 20rpx;
    border-radius: 12rpx;
    padding: 30rpx;
    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);

    .news-card {
      background-color: #f9f9f9;
      border-radius: 8rpx;
      padding: 20rpx;
      margin-bottom: 20rpx;

      .news-header {
        margin-bottom: 16rpx;

        .news-title {
          font-size: 30rpx;
          font-weight: bold;
          color: $text-color;
          margin-bottom: 8rpx;
          display: block;
        }

        .news-time {
          font-size: 24rpx;
          color: #999999;
        }
      }

      .news-content {
        display: flex;
        margin-bottom: 20rpx;

        .news-image {
          width: 180rpx;
          height: 120rpx;
          border-radius: 6rpx;
          margin-right: 16rpx;
          flex-shrink: 0;
          background-color: #f0f0f0;
        }

        .news-info {
          flex: 1;
          display: flex;
          flex-direction: column;
          justify-content: space-between;

          .news-source {
            font-size: 26rpx;
            color: #666666;
            margin-bottom: 8rpx;
          }

          .news-link {
            font-size: 24rpx;
            color: $theme-color;
            word-break: break-all;
          }
        }
      }

      .news-actions {
        display: flex;
        justify-content: flex-end;
        border-top: 2rpx solid $border-color;
        padding-top: 16rpx;

        .action-button {
          margin-left: 30rpx;

          .action-text {
            font-size: 26rpx;
          }

          &.edit .action-text {
            color: $theme-color;
          }

          &.delete .action-text {
            color: $danger-color;
          }
        }
      }
    }

    .empty-list {
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 60rpx 0;

      .empty-icon {
        width: 160rpx;
        height: 160rpx;
        margin-bottom: 20rpx;
        opacity: 0.5;
      }

      .empty-text {
        font-size: 28rpx;
        color: #999999;
      }
    }

    .pagination-info {
      margin-top: 20rpx;
      text-align: center;
      font-size: 26rpx;
      color: #999999;

      .page-text {
        margin-right: 20rpx;
      }

      .total-text {
        margin-left: 20rpx;
      }
    }

    .load-more {
      margin-top: 20rpx;
      text-align: center;

      .load-more-btn {
        width: 200rpx;
        height: 88rpx;
        background: linear-gradient(to right, $theme-color, #8067dc);
        color: #ffffff;
        font-size: 32rpx;
        font-weight: 500;
        border-radius: 44rpx;
        display: flex;
        align-items: center;
        justify-content: center;

        &:active {
          opacity: 0.9;
        }

        &::after {
          border: none;
        }
      }
    }
  }
}
</style>
